package com.zyq.validation.exception;

import java.util.Map;
import java.util.Map;
import java.util.HashMap;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
@Slf4j
public class GlobalException {

//catchMethodArgumentNotValidException


/*    @ExceptionHandler(MethodArgumentNotValidException.class)//捕获所有controller的MethodArgumentNotValidException异常
    @ResponseBody
    public ResponseEntity<Object> exception(MethodArgumentNotValidException e, HttpServletRequest request) {
        Map<String, String> result = new HashMap<>();
        BindingResult bindingResult = e.getBindingResult();//获取异常结果信息
        //request.getMethod():请求方式，request.getRequestURI() 请求路径 //比如:  post    /reg2
        log.error("请求[ {} ] {} 的参数校验发生错误", request.getMethod(), request.getRequestURL());
        for (ObjectError objectError : bindingResult.getAllErrors()) {
            FieldError fieldError = (FieldError) objectError;//验证失败后，Spring会生成一个FieldError对象，其中包含了错误的详细信息
            //fieldError.getField():获取引发FieldError的被拒绝的key(方法返回的是导致FieldError的那个字段的字段名)
            //fieldError.getRejectedValue():获取引发FieldError的被拒绝的value(方法返回的是导致FieldError的那个字段的值，即那个无法通过验证的值。)
            //fieldError.getDefaultMessage(): 获取到错误提示
            log.error("参数 {} = {} 校验错误：{}", fieldError.getField(), fieldError.getRejectedValue(), fieldError.getDefaultMessage());
            result.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        // 一般项目都会有自己定义的公共返回实体类，这里直接使用现成的 ResponseEntity 进行返回，同时设置 Http 状态码为 400
        return ResponseEntity.badRequest().body(result);
    }*/


    //这里可以采用同一个方法并且在@ExceptionHandler中指定多个异常类型，并且在for循环中获取多个字段校验结果返回
    //可以将上边的方法进行合并
    @ExceptionHandler(BindException.class)//捕获所有controller的BindException异常
    @ResponseBody
    public ResponseEntity<Object> exception(BindException e, HttpServletRequest request) {
        Map<String, String> result = new HashMap<>();
        BindingResult bindingResult = e.getBindingResult();//获取异常结果信息
        //request.getMethod():请求方式，request.getRequestURI() 请求路径 //比如:  post    /reg2
        log.error("请求[ {} ] {} 的参数校验发生错误", request.getMethod(), request.getRequestURL());
        for (ObjectError objectError : bindingResult.getAllErrors()) {
            FieldError fieldError = (FieldError) objectError;//验证失败后，Spring会生成一个FieldError对象，其中包含了错误的详细信息
            //fieldError.getField():获取引发FieldError的被拒绝的key(方法返回的是导致FieldError的那个字段的字段名)
            //fieldError.getRejectedValue():获取引发FieldError的被拒绝的value(方法返回的是导致FieldError的那个字段的值，即那个无法通过验证的值。)
            //fieldError.getDefaultMessage(): 获取到错误提示
            log.error("参数 {} = {} 校验错误：{}", fieldError.getField(), fieldError.getRejectedValue(), fieldError.getDefaultMessage());
            result.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        // 一般项目都会有自己定义的公共返回实体类，这里直接使用现成的 ResponseEntity 进行返回，同时设置 Http 状态码为 400
        return ResponseEntity.badRequest().body(result);
    }

    @ExceptionHandler(AgeOutOfRangeException.class)//捕获所有controller的BindException异常
    @ResponseBody
    public ResponseEntity<Object> exception(AgeOutOfRangeException e, HttpServletRequest request) {
        Map<String, String> result = new HashMap<>();
        //request.getMethod():请求方式，request.getRequestURI() 请求路径 //比如:  post    /reg2
        log.error("请求[ {} ] {} 的参数校验发生错误", request.getMethod(), request.getRequestURL());
        log.error("参数 {} = {} 校验错误：{}", e.getKey(), e.getVal(), e.getMessage());
        result.put(e.getKey(), e.getMessage());
        // 一般项目都会有自己定义的公共返回实体类，这里直接使用现成的 ResponseEntity 进行返回，同时设置 Http 状态码为 400
        return ResponseEntity.badRequest().body(result);
    }




    /*@ExceptionHandler(MethodArgumentNotValidException.class)//捕获所有controller的MethodArgumentNotValidException异常
    @ResponseBody
    public ResponseEntity<Object> catchMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request){
        Map<String, String> result=new HashMap<>();
        BindingResult rs=e.getBindingResult();//获取异常结果信息
        log.error("请求[{}] {} 的参数校验发生错误", request.getMethod(), request.getRequestURI());//请求的方法名和uri
        for(ObjectError error: rs.getAllErrors()){
            FieldError fieldError=(FieldError) error;//验证失败后，Spring会生成一个FieldError对象，其中包含了错误的详细信息
            //fieldError.getField():获取引发FieldError的被拒绝的key(方法返回的是导致FieldError的那个字段的字段名)
            //fieldError.getRejectedValue():获取引发FieldError的被拒绝的value(方法返回的是导致FieldError的那个字段的值，即那个无法通过验证的值。)
            //fieldError.getDefaultMessage(): 获取到错误提示
            log.error("参数{} = {}校验错误:{}", fieldError.getField(), fieldError.getRejectedValue(), fieldError.getDefaultMessage());
            result.put(fieldError.getField(),fieldError.getDefaultMessage());
        }
        return ResponseEntity.badRequest().body(request);
    }*/

}